//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Media3D;

namespace OpenLS.Chart.UI
{
    internal sealed class CameraConverter : IMultiValueConverter
    {
        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values[0] == DependencyProperty.UnsetValue)
                return null;
            double xAngle = System.Convert.ToDouble(values[0]);
            double yAngle = System.Convert.ToDouble(values[1]);
            var xMin = (double) values[2];
            var xMax = (double) values[3];
            var yMin = (double) values[4];
            var yMax = (double) values[5];
            var zMin = (double) values[6];
            var zMax = (double) values[7];
            Debug.WriteLine(string.Format("CameraConverter,  ymin = {0} yMax = {1}", yMin, yMax));
            //  xMin = Math.Min(xMin, 0);
            //  yMin = Math.Min(yMin, 0);
            //Point3D center = new Point3D((xMax + xMin) / 2, (yMax + yMin) / 2, 0)

            double xFactor;
            double yFactor;
            double zFactor;
            double xTranslate;
            double yTranslate;
            double zTranslate;
            computeSuff(xMin, xMax, -0.5, 0.5, out xFactor, out xTranslate);
            computeSuff(yMin, yMax, -0.5, 0.5, out yFactor, out yTranslate);
            computeSuff(zMin, zMax, -0.5, 0, out zFactor, out zTranslate);
            var viewMatrix = new Matrix3D(
                xFactor, 0, 0, 0,
                0, yFactor, 0, 0,
                0, 0, zFactor, 0,
                xTranslate, yTranslate, zTranslate, 1);
            const double factor = 0.5;
            var projectionMatrix = new Matrix3D(
                1, 0, 0, 0,
                0, 1, 0, 0,
                -Math.Sin(xAngle/180*Math.PI)*factor, -Math.Sin(yAngle/180*Math.PI)*factor, -0.5, 0,
                0, 0, 0, 1);
            var result = new MatrixCamera(viewMatrix, projectionMatrix);
            return result;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        #endregion

        private static void computeSuff(double min, double max, double realMin, double realMax, out double factor,
                                        out double translate)
        {
            if (max <= min)
                factor = 1;
            else
                factor = (realMax - realMin) / (max - min);

            translate = -factor*min + realMin;
        }
    }
}